#include "StdAfx.h"
#include "admindbmanager.h"
#include "topicdetaildialog.h"

TopicTableManager::TopicTableManager( QObject * parent )
:   DataTableManagerBase( parent )
{
}
TopicTableManager::~TopicTableManager()
{
}

bool TopicTableManager::selectToTableModel( const QString & filterStr )
{
    m_standardModel.setColumnCount( 2 );
    m_standardModel.setHeaderData( 0, Qt::Horizontal, QObject::tr( "Name" ) );
    m_standardModel.setHeaderData( 1, Qt::Horizontal, QObject::tr( "Category" ) );

    Selector selector;
    DbString commandStr( selector.dbConnection(), selector.stmt(), "SELECT id, name, category FROM topics" );
    if (! selector.select( commandStr ))
        return false;

    int row = 0;
    while (selector.read())
    {
        Topic topic;
        topic.id = selector.getInt64( 0 );
        topic.name = selector.getString( 1 );
        topic.category = selector.getNvlInt32( 2, InvalidId );

        updateModel( row, topic );
        row ++;
    }

    return true;
}

void TopicTableManager::updateModel( int row, const Topic & topic )
{
    QStandardItem * itemName;

    itemName = new QStandardItem( topic.name );
    m_standardModel.setItem( row, 0, itemName );
    itemName->setData( QVariant( topic.id ) );

    QString categoryStr;
    if (isFlag( topic.category, TopicCategory::Bible ))
    {
        categoryStr.append( TopicCategory::toString( TopicCategory::Bible ) );
        categoryStr.append( ", " );
    }
    if (isFlag( topic.category, TopicCategory::Teo ))
    {
        categoryStr.append( TopicCategory::toString( TopicCategory::Teo ) );
        categoryStr.append( ", " );
    }
    if (isFlag( topic.category, TopicCategory::Scientific ))
    {
        categoryStr.append( TopicCategory::toString( TopicCategory::Scientific ) );
        categoryStr.append( ", " );
    }
    if (isFlag( topic.category, TopicCategory::Humanitarian ))
    {
        categoryStr.append( TopicCategory::toString( TopicCategory::Humanitarian ) );
        categoryStr.append( ", " );
    }

    if (! categoryStr.isEmpty())
        categoryStr.resize( categoryStr.count() - 2 );

    itemName = new QStandardItem( categoryStr );
    m_standardModel.setItem( row, 1, itemName );
}

///////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////

QuestionTableManager::QuestionTableManager( QObject * parent, QVector<Question> & questionVector )
:   DataTableManagerBase( parent ),
    m_questionVector( questionVector )
{
}
QuestionTableManager::~QuestionTableManager()
{
}

bool QuestionTableManager::selectToTableModel( const QString & filterStr )
{
    m_standardModel.setColumnCount( 3 );
    m_standardModel.setHeaderData( 0, Qt::Horizontal, QObject::tr( "Question" ) );
    m_standardModel.setHeaderData( 1, Qt::Horizontal, QObject::tr( "Answer" ) );
    m_standardModel.setHeaderData( 2, Qt::Horizontal, QObject::tr( "Value" ) );

    int row = 0;
    QVector<Question>::const_iterator it;
    FOREACH (it, m_questionVector)
    {
        updateModel( row, * it );
        row ++;
    }

    return true;
}

void QuestionTableManager::updateModel( int row, const Question & question )
{
    QStandardItem * itemName;

    // nejake nacpanie do riadku
    itemName = new QStandardItem( question.question );
    m_standardModel.setItem( row, 0, itemName );
    itemName->setData( QVariant( question.id ) );

    itemName = new QStandardItem( question.answer );
    m_standardModel.setItem( row, 1, itemName );

    itemName = new QStandardItem( QString( "%1" ).arg( question.value ) );
    m_standardModel.setItem( row, 2, itemName );
}

///////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////

TopicManager::TopicManager( QWidget * parent )
:   ManagerBase( parent ),
    m_topicTableManager( parent )
{
}

TopicManager::~TopicManager()
{
}

DataTableManagerBase & TopicManager::dataTableManager()
{
    return m_topicTableManager;
}

void TopicManager::add()
{
    TopicDetailDialog topicDetailDialog( & m_parent );
    if (topicDetailDialog.exec() != QDialog::Accepted)
        return;

    Topic newTopic = topicDetailDialog.topic();
    SqlCommand sqlCommand;
    
    if (! TopicDbManager::insertTopicToDb( sqlCommand, newTopic, newTopic.id ))
        return;

    if (! sqlCommand.commit())
        return;

    int rowCount = m_topicTableManager.tableModelBase().rowCount();
    m_topicTableManager.updateModel( rowCount, newTopic );
    m_topicTableManager.selectRow( rowCount );
}

void TopicManager::update( int row, const qint64 & id )
{
    Topic topic;
    if (! TopicDbManager::selectTopicDetailsFromDb( id, topic ))
        return;
    
   TopicDetailDialog topicDetailDialog( & m_parent, topic );
    if (topicDetailDialog.exec() != QDialog::Accepted)
        return;

    Topic updatedTopic = topicDetailDialog.topic();
    SqlCommand sqlCommand;

    if (! TopicDbManager::updateTopicInDb( sqlCommand, updatedTopic ))
        return;

    if (! sqlCommand.commit())
        return;

    m_topicTableManager.updateModel( row, updatedTopic ); 
}

void TopicManager::remove( int row, const qint64 & id )
{
    if (! questionBox( QObject::tr( "Delete topic" ), QObject::tr( "Do you really want to delete selected topic?" ) ))
        return;
    
    SqlCommand sqlCommand;
    if (! TopicDbManager::deleteTopicFromDb( sqlCommand, id ))
        return;

    if (sqlCommand.commit())
        m_topicTableManager.tableModelBase().removeRows( row, 1 );
    
}

void TopicManager::executeAction( int actionId, int standardModelRow, const QStandardItem * item )
{
    QVariant variant;
    if (item != NULL)
    {
        variant = item->data( Qt::UserRole + 1 );
    }

    switch (actionId)
    {
    case ActionBase::New:
        add();
        break;

    case ActionBase::Update:
        if (! variant.isValid())
        {
            assert( 0 );
            return;
        }

        update( standardModelRow, variant.toLongLong() );
        break;

    case ActionBase::Delete:
        if (! variant.isValid())
        {
            assert( 0 );
            return;
        }

        remove( standardModelRow, variant.toLongLong() );
        break;

    default:
        assert( 0 );
        break;
    }
}

void TopicManager::executeDoubleClickAction( int standardModelRow, const QStandardItem * item )
{
    if (item == NULL)
        return;
    
    QVariant variant = item->data( Qt::UserRole + 1 );
    if (! variant.isValid())
        return;

    update( standardModelRow, variant.toLongLong() );
}

///////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////

bool TopicDbManager::insertTopicToDb( SqlCommand & sqlCommand, const Topic & topic, qint64 & newId )
{
    newId = InvalidId;
    if (! sqlCommand.selectNewId( "topics", newId ))
        return false;

    DbString commandStr = DbString( sqlCommand.dbConnection(), sqlCommand.stmt(), "INSERT INTO topics ( id, name, category ) VALUES ( ?, ?, ? ) " )
        .argValue( newId )
        .argValue( topic.name )
        .argValue( topic.category );

    if (! sqlCommand.executeQuery( commandStr ))
        return false;

    QVector<Question>::const_iterator it;
    FOREACH (it, topic.questionVector)
    {
        qint64 newQuestionId = InvalidId;
        if (! sqlCommand.selectNewId( "questions", newQuestionId ))
            return false;

        commandStr = DbString( sqlCommand.dbConnection(), sqlCommand.stmt(), "INSERT INTO questions ( id, topicid, question, answer, value ) VALUES ( ?, ?, ?, ?, ? ) " )
            .argValue( newQuestionId )
            .argValue( newId )
            .argValue( it->question )
            .argValue( it->answer )
            .argValue( it->value );

        if (! sqlCommand.executeQuery( commandStr ))
            return false;
    }

    return true;
}

bool TopicDbManager::updateTopicInDb( SqlCommand & sqlCommand, const Topic & topic )
{
    DbString commandStr = DbString( sqlCommand.dbConnection(), sqlCommand.stmt(), "UPDATE topics SET name = ?, category = ? WHERE id = ?" )
        .argValue( topic.name )
        .argValue( topic.category )
        .argValue( topic.id );
        
    if (! sqlCommand.executeQuery( commandStr ))
        return false;

    QSet<qint64> idSet;
    Selector selector;
    if (! selector.select( DbString( selector.dbConnection(), selector.stmt(), "SELECT id FROM questions WHERE topicid = ?" ).argValue( topic.id ) ))
        return false;

    while (selector.read())
    {
        qint64 id = selector.getInt64( 0 );
        idSet.insert( id );
    }

    QVector<Question>::const_iterator it;
    FOREACH (it, topic.questionVector)
    {
        if (idSet.find( it->id ) == idSet.end())
        {
            qint64 newQuestionId = InvalidId;
            if (! sqlCommand.selectNewId( "questions", newQuestionId ))
                return false;

            commandStr = DbString( sqlCommand.dbConnection(), sqlCommand.stmt(), "INSERT INTO questions ( id, topicid, question, answer, value ) VALUES ( ?, ?, ?, ?, ? ) " )
                .argValue( newQuestionId )
                .argValue( topic.id )
                .argValue( it->question )
                .argValue( it->answer )
                .argValue( it->value );
        }
        else
        {
            commandStr = DbString( sqlCommand.dbConnection(), sqlCommand.stmt(), "UPDATE questions SET question = ?, answer = ?, value = ? WHERE id = ?" )
                .argValue( it->question )
                .argValue( it->answer )
                .argValue( it->value )
                .argValue( it->id );

            idSet.remove( it->id );
        }

        if (! sqlCommand.executeQuery( commandStr ))
            return false;
    }

    QSet<qint64>::const_iterator iter;
    FOREACH (iter, idSet)
    {
        commandStr = DbString( sqlCommand.dbConnection(), sqlCommand.stmt(), "DELETE FROM questions WHERE id = ?" ).argValue( * iter );
        if (! sqlCommand.executeQuery( commandStr ))
            return false;
    }

    return true;
}

bool TopicDbManager::deleteTopicFromDb( SqlCommand & sqlCommand, const qint64 & id )
{
    if (! sqlCommand.executeQuery( DbString( sqlCommand.dbConnection(), sqlCommand.stmt(), "DELETE FROM questions WHERE topicid = ?" ).argValue( id ) ))
        return false;

    return sqlCommand.executeQuery( DbString( sqlCommand.dbConnection(), sqlCommand.stmt(), "DELETE FROM topics WHERE id = ?" ).argValue( id ) );
}

bool TopicDbManager::selectTopicDetailsFromDb( const qint64 & id, Topic & topic )
{
    Selector selector;
    DbString commandStr = DbString( selector.dbConnection(), selector.stmt(), "SELECT name, category FROM topics WHERE id = ?" ).argValue( id );
    if (! selector.select( commandStr ))
        return false;

    if (selector.isEmptySelect())
    {
        errorBox( QObject::tr( "No topic details" ) );
        return false;
    }

    topic.id = id;
    topic.name = selector.getString( 0 );
    topic.category = selector.getInt32( 1 );

    commandStr = DbString( selector.dbConnection(), selector.stmt(), "SELECT id, question, answer, value FROM questions WHERE topicid = ?" ).argValue( id );
    if (! selector.select( commandStr ))
        return false;

    while (selector.read())
    {
        Question question;

        question.id = selector.getInt64( 0 );
        question.topicId = id;
        question.question = selector.getString( 1 );
        question.answer = selector.getString( 2 );
        question.value = selector.getInt32( 3 );

        topic.questionVector.push_back( question );
    }

    return true;
}

bool TopicDbManager::readTopicsIdVector( int topicCategory, int minimumQuestionCount, QVector<qint64> & topicIdVector )
{
    Selector selector;
    DbString commandStr = DbString( selector.dbConnection(), selector.stmt(), 
        "SELECT id FROM topics WHERE ( category & ? ) != 0 AND "
        "( SELECT count( 1 ) FROM questions WHERE topicId = topics.id ) >= ? " )    
        .argValue( topicCategory )
        .argValue( minimumQuestionCount );

    if (! selector.select( commandStr ))
        return false;

    while (selector.read())
    {
        qint64 topicId = selector.getInt64( 0 );
        topicIdVector.push_back( topicId );
    }

    return true;
}